import {
  isUndefined,
  isNull,
  getTSFromPb,
  toString,
  PagedList,
  PageParams,
} from "mmb";
import * as activity_statpb from "../grpc-client/service/activity_stat_pb";
import {
  getBgsActivityStatOpSafely,
  getMetadata,
  getOptionsOfLight,
  wrapperGrpcError,
} from "../grpc-client/grpcAdapter";
import { pbTimestampToJs, jsTimestampToPb } from "./helper";
import {
  AggrActivityExposureStat,
  AggrActivityOrderStat,
  AggrActivityStatsOfBrandRet,
  AggrActivityStatsOfSpokesmanRet,
  AggrActivityConsignment,
  AggrActivityConsignmentForSpokesman,
  RankActivityItemOfStoreForDistributorWithStatsOverOrderAmount,
  RankOverOrderAmountForSpokesman,
} from "./declareTypes";

/****************************************************************************************/
/*                                   activity_order_stat aggs query                     */
/****************************************************************************************/

const aggsToActivityExposureStatPbToObject = (
  pb: activity_statpb.AggrActivityExposureStatEntity
): AggrActivityExposureStat => {
  return {
    pv: pb.getPv(),
    uv: pb.getUv(),
    iv: pb.getIv(),
  };
};

const aggsToActivityOrderStatPbToObject = (
  pb: activity_statpb.AggrActivityOrderStatEntity
): AggrActivityOrderStat => {
  return {
    buyerCount: pb.getBuyerCount(),
    orderCount: pb.getOrderCount(),
    orderAmount: pb.getOrderAmount(),
    distributeAmount: pb.getDistributeAmount(),
    orderBonus: pb.getOrderBonus(),
    fee: pb.getFee(),
    wxpayCommission: pb.getWxpayCommission(),
    platformCommission: pb.getPlatformCommission(),
    refundBuyerCount: pb.getRefundBuyerCount(),
    refundOrderCount: pb.getOrderCount(),
    refundOrderAmount: pb.getRefundOrderAmount(),
    refundDistributeAmount: pb.getRefundDistributeAmount(),
    refundOrderBonus: pb.getRefundOrderBonus(),
    refundFee: pb.getRefundFee(),
    refundWxpayCommission: pb.getRefundWxpayCommission(),
    refundPlatformCommission: pb.getRefundPlatformCommission(),
  };
};

const rankActivityItemOfStoreForDistributorWithStatsOverOrderAmountPbToObject =
  (
    pb: activity_statpb.RankActivityItemOfStoreForDistributorWithStatsOverOrderAmountEntity
  ): RankActivityItemOfStoreForDistributorWithStatsOverOrderAmount => {
    return {
      activityId: toString(pb.getActivityId()),
      name: pb.getName(),
      orderAmount: pb.getOrderAmount(),
      orderCount: pb.getOrderCount(),
    };
  };

export const aggrActivityStatsOfBrandByActivityID = async (
  activityId: string,
  brandId: string
): Promise<AggrActivityStatsOfBrandRet> => {
  const cl = getBgsActivityStatOpSafely();
  const req = new activity_statpb.AggrActivityStatsOfBrandByActivityIDRequest();

  req.setActivityId(Number(activityId));
  req.setBrandId(Number(brandId));

  return new Promise((resolve, reject) => {
    cl.aggrActivityStatsOfBrandByActivityID(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }

        let ret: AggrActivityStatsOfBrandRet = {
          exposure: {
            own: aggsToActivityExposureStatPbToObject(
              res.getAggrExposureOfOwn()!
            ),
            endorsement: aggsToActivityExposureStatPbToObject(
              res.getAggrExposureOfEndorsement()!
            ),
          },
          order: {
            own: aggsToActivityOrderStatPbToObject(res.getAggrOrderOfOwn()!),
            endorsement: aggsToActivityOrderStatPbToObject(
              res.getAggrOrderOfEndorsement()!
            ),
          },
        };

        resolve(ret);
      }
    );
  });
};

export const aggrActivityStatsOfStoreByActivityID = async (
  activityId: string,
  storeId: string
): Promise<AggrActivityStatsOfBrandRet> => {
  const cl = getBgsActivityStatOpSafely();
  const req = new activity_statpb.AggrActivityStatsOfStoreByActivityIDRequest();

  req.setActivityId(Number(activityId));
  req.setStoreId(Number(storeId));

  return new Promise((resolve, reject) => {
    cl.aggrActivityStatsOfStoreByActivityID(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }

        let ret: AggrActivityStatsOfBrandRet = {
          exposure: {
            own: aggsToActivityExposureStatPbToObject(
              res.getAggrExposureOfOwn()!
            ),
            endorsement: aggsToActivityExposureStatPbToObject(
              res.getAggrExposureOfEndorsement()!
            ),
          },
          order: {
            own: aggsToActivityOrderStatPbToObject(res.getAggrOrderOfOwn()!),
            endorsement: aggsToActivityOrderStatPbToObject(
              res.getAggrOrderOfEndorsement()!
            ),
          },
        };

        resolve(ret);
      }
    );
  });
};

export const aggrActivityStatsOfSpokesmanByActivityID = async (
  activityId: string,
  spokesmanId: string
): Promise<AggrActivityStatsOfSpokesmanRet> => {
  const cl = getBgsActivityStatOpSafely();
  const req =
    new activity_statpb.AggrActivityStatsOfSpokesmanByActivityIDRequest();

  req.setActivityId(Number(activityId));
  req.setSpokesmanId(Number(spokesmanId));

  return new Promise((resolve, reject) => {
    cl.aggrActivityStatsOfSpokesmanByActivityID(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        let ret: AggrActivityStatsOfSpokesmanRet = {
          exposure: aggsToActivityExposureStatPbToObject(
            res.getAggrExposureOfEndorsement()!
          ),
          order: aggsToActivityOrderStatPbToObject(
            res.getAggrOrderOfEndorsement()!
          ),
        };
        resolve(ret);
      }
    );
  });
};

export const rankActivityItemOfStoreForDistributorWithStatsOverOrderAmount =
  async (
    distributorId: string,
    pager: PageParams
  ): Promise<
    PagedList<RankActivityItemOfStoreForDistributorWithStatsOverOrderAmount>
  > => {
    const cl = getBgsActivityStatOpSafely();
    const req =
      new activity_statpb.RankActivityItemOfStoreForDistributorWithStatsOverOrderAmountRequest();

    req.setLimit(pager.limit);
    req.setOffset(pager.offset);
    req.setTs(jsTimestampToPb(pager.ts));
    req.setDistributorId(Number(distributorId));

    return new Promise((resolve, reject) => {
      cl.rankActivityItemOfStoreForDistributorWithStatsOverOrderAmount(
        req,
        getMetadata(),
        getOptionsOfLight(),
        (err, res) => {
          if (!isNull(err)) {
            reject(wrapperGrpcError(err.details));
            return;
          }
          const opRet = res.getOpRet()!;
          if (!opRet.getSuccess()) {
            reject(wrapperGrpcError(opRet.getMsg()));
            return;
          }

          const ret: PagedList<RankActivityItemOfStoreForDistributorWithStatsOverOrderAmount> =
            {
              total: 0,
              items: [],
            };
          ret.total = res.getTotal();
          ret.items = res
            .getActivityItemOfStoreForDistributorWithStatsList()
            .map(
              rankActivityItemOfStoreForDistributorWithStatsOverOrderAmountPbToObject
            );
          resolve(ret);
        }
      );
    });
  };

/****************************************************************************************/
/*                                   activity_user_order_stat aggs query                */
/****************************************************************************************/

const aggsToActivityConsignmentPbToObject = (
  pb: activity_statpb.AggrActivityConsignmentEntity
): AggrActivityConsignment => {
  return {
    spokesmanCount: pb.getSpokesmanCount(),
    consignmentAmount: pb.getConsignmentAmount(),
  };
};

const aggsToActivityConsignmentForSpokesmanPbToObject = (
  pb: activity_statpb.AggrActivityConsignmentForSpokesmanEntity
): AggrActivityConsignmentForSpokesman => {
  return {
    orderCount: pb.getOrderCount(),
    orderAmount: pb.getOrderAmount(),
    orderBonus: pb.getOrderBonus(),
    spokesmanId: toString(pb.getSpokesmanId()),
    spokesmanUserId: toString(pb.getSpokesmanUserId()),
    published: pbTimestampToJs(pb.getPublished())!,
    spokesmanUserNickName: pb.getSpokesmanUserNickName(),
    spokesmanUserPic: pb.getSpokesmanUserPic(),
    spokesmanUserMobile: pb.getSpokesmanUserMobile(),
  };
};

const rankOverOrderAmountForSpokesmanPbToObject = (
  pb: activity_statpb.RankOverOrderAmountForSpokesmanEntity
): RankOverOrderAmountForSpokesman => {
  return {
    orderAmount: pb.getOrderAmount(),
    refundOrderAmount: pb.getRefundOrderAmount(),
    orderBonus: pb.getOrderBonus(),
    orderAmountRank: pb.getOrderAmountRank(),
    spokesmanId: toString(pb.getSpokesmanId()),
    spokesmanUserId: toString(pb.getSpokesmanUserId()),
    spokesmanUserNickName: pb.getSpokesmanUserNickName(),
  };
};

export const aggrConsignmentByActivityID = async (
  activityId: string
): Promise<AggrActivityConsignment> => {
  const cl = getBgsActivityStatOpSafely();
  const req = new activity_statpb.AggrConsignmentByActivityIDRequest();

  req.setActivityId(Number(activityId));

  return new Promise((resolve, reject) => {
    cl.aggrConsignmentByActivityID(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        resolve(
          aggsToActivityConsignmentPbToObject(res.getAggrActivityConsignment()!)
        );
      }
    );
  });
};

export const aggrConsignmentForSpokesmanByActivityID = async (
  activityId: string
): Promise<AggrActivityConsignmentForSpokesman[]> => {
  const cl = getBgsActivityStatOpSafely();
  const req =
    new activity_statpb.AggrConsignmentForSpokesmanByActivityIDRequest();

  req.setActivityId(Number(activityId));

  return new Promise((resolve, reject) => {
    cl.aggrConsignmentForSpokesmanByActivityID(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        resolve(
          res
            .getAggrActivityConsignmentForSpokesmanList()
            .map(aggsToActivityConsignmentForSpokesmanPbToObject)
        );
      }
    );
  });
};

export const rankOverOrderAmountForSpokesmanByActivityID = async (
  activityId: string,
  topRankNumber: number
): Promise<RankOverOrderAmountForSpokesman[]> => {
  const cl = getBgsActivityStatOpSafely();
  const req =
    new activity_statpb.RankOverOrderAmountForSpokesmanByActivityIDRequest();

  req.setActivityId(Number(activityId));
  req.setTopRankNumber(topRankNumber);

  return new Promise((resolve, reject) => {
    cl.rankOverOrderAmountForSpokesmanByActivityID(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        resolve(
          res
            .getRankOverOrderAmountForSpokesmansList()
            .map(rankOverOrderAmountForSpokesmanPbToObject)
        );
      }
    );
  });
};
